﻿#region License statement
// NJamb, a specification and delta-specification DSL
// Copyright (c) 2010-2011, Mark Knell
// Published under the MIT License; all other rights reserved
#endregion

#region using...
using System;
using System.Collections.Generic;
using NJamb.Parser.SpecificationBuilders.SubjectHas.Simple.Enumerable.Quantifiers;
using NJamb.Specifications;
using Stile.Patterns.SelfDescribingPredicates;
using Stile.Patterns.SelfDescribingPredicates.Evaluators;
#endregion

namespace NJamb.Parser.SpecificationBuilders.SubjectHas.AbstractEnumerable
{
    public abstract class AbstractEnumerableHas<TSubject, TItem, TSpecifies> : FluentHas<TSubject, TSpecifies>
        where TSubject : class, IEnumerable<TItem>
        where TSpecifies : class, ISpecification
    {
        protected AbstractEnumerableHas(ICollaboratingSpecificationBuilder<TSubject, TSpecifies> specificationBuilder)
            : base(specificationBuilder)
        {
            LazyAll =
                new Lazy<IEnumerableQuantifiedHas<TItem, TSpecifies>>(
                    () => new HasAll<TSubject, TItem, TSpecifies>(specificationBuilder));
            LazyNo =
                new Lazy<IEnumerableQuantifiedHas<TItem, TSpecifies>>(
                    () => new HasNo<TSubject, TItem, TSpecifies>(specificationBuilder));
            LazyOne =
                new Lazy<IEnumerableQuantifiedHas<TItem, TSpecifies>>(
                    () => new HasOne<TSubject, TItem, TSpecifies>(specificationBuilder));
            LazySome =
                new Lazy<IEnumerableQuantifiedHas<TItem, TSpecifies>>(
                    () => new HasSome<TSubject, TItem, TSpecifies>(specificationBuilder));
        }

        public IEnumerableQuantifiedHas<TItem, TSpecifies> All
        {
            get { return LazyAll.Value; }
        }

        public Lazy<IEnumerableQuantifiedHas<TItem, TSpecifies>> LazyAll { get; private set; }
        public Lazy<IEnumerableQuantifiedHas<TItem, TSpecifies>> LazyNo { get; private set; }
        public Lazy<IEnumerableQuantifiedHas<TItem, TSpecifies>> LazyOne { get; private set; }
        public Lazy<IEnumerableQuantifiedHas<TItem, TSpecifies>> LazySome { get; private set; }

        public IEnumerableQuantifiedHas<TItem, TSpecifies> No
        {
            get { return LazyNo.Value; }
        }
        public IEnumerableQuantifiedHas<TItem, TSpecifies> One
        {
            get { return LazyOne.Value; }
        }
        public IEnumerableQuantifiedHas<TItem, TSpecifies> Some
        {
            get { return LazySome.Value; }
        }

        public TSpecifies CountOf(int count)
        {
            Evaluator<TSubject, int> evaluator = ExpectEnumerable<TSubject, TItem>.CountOf(count);
            return SpecificationBuilder.Specify(evaluator);
        }
    }
}
